package com.quick.aspect;

import com.quick.util.SpelUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.quick.annotation.RedisLock;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class LockAspect {
	
	private static final Logger log = LoggerFactory.getLogger(LockAspect.class);
	
	@Autowired
	private RedissonClient redissonClient;
	
	
	@Pointcut("@annotation(com.quick.annotation.RedisLock)") 
	public void quickLock() {}

	@Around("quickLock() && @annotation(redisLock)")
	public Object around(ProceedingJoinPoint pjp,RedisLock redisLock) {
		String value = redisLock.value();
		Signature signature = pjp.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method targetMethod = methodSignature.getMethod();
		Object target = pjp.getTarget();
		Object[] arguments = pjp.getArgs();
		String key  = SpelUtil.parse(target,value, targetMethod, arguments);
		RLock rLock = redissonClient.getFairLock ( key );
		try {
			boolean lock = rLock.tryLock(redisLock.waitTime()*1L, redisLock.expireTime()*1L, TimeUnit.SECONDS);
			if(lock){
				 log.info("加锁");
				 Object res = pjp.proceed();
				 log.info("处理对象{}",res);
				 return  res;
			}
		} catch (Exception e) {
            throw new RuntimeException(e);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        } finally {
			log.info("解锁");
			rLock.unlock();
		}
        return target;
    }



}
